package com.xiyuan.smartutils.template.engine.statement;

import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.Validates;
import com.xiyuan.smartutils.template.engine.StatementParser;
import com.xiyuan.smartutils.template.engine.TagType;
import com.xiyuan.smartutils.template.engine.VariableMap;
import com.xiyuan.smartutils.template.engine.exception.StatementException;

import java.io.PrintWriter;

public class _Var extends Statement
{
    private static final long serialVersionUID = 1L;
    private String variableName;
    
    public _Var(StatementParser parser)
    {
        super(parser);
    }
    
    @Override
    protected void build(VariableMap variableMap, PrintWriter out)
    {
        if (!expressions.isEmpty())
            variableMap.putValue(variableName, expressions.get(0).execute(variableMap));
    }
    
    @Override
    public TagType getType()
    {
        return TagType.VAR;
    }
    
    @Override
    public boolean parseTag(StatementParser parser) throws StatementException
    {
        StringBuilder value = new StringBuilder();
        // String variableName = null;
        int expression_begin_line = this.getLineNo(), expression_begin_column = this.getBeginColumn();
        int equal_line = expression_begin_line, equal_column = 0;// 等号发现的行数,以及位置
        char ch = 0, quote = 0, prvChar = 0;
        boolean space = false;
        while (parser.hasNext())
        {
            prvChar = value.length() == 0 ? 0 : ch;
            ch = parser.next();
            if (value.length() == 0 && Validates.isWhitespace(ch))
            {
                space = true;
                continue;
            }
            
            value.append(ch);
            if (!space)
                return false;// 只是以#var开头而已
                
            if (value.length() == 1)
            {
                expression_begin_line = parser.getLineNum();
                expression_begin_column = parser.getColumn();
            }
            
            if (variableName == null)
            {// 未找到变量名时
            
                if ('=' == ch)
                {// 找到变量名
                    if (value.length() == 1)
                        throw new StatementException(this.getPath(), expression_begin_line, expression_begin_column, StrUtils.formats("%s找到变量名", getType()));
                    
                    variableName = StrUtils.trim(value.substring(0, value.length() - 1));
                    if (!Validates.isJavaNameIdentifier(variableName))
                        throw new StatementException(this.getPath(), expression_begin_line, expression_begin_column, StrUtils.formats("%s标签解析时无效变量名,请参见java命名规范。当前值【%s】", getType(),
                            variableName));
                    
                    equal_line = parser.getLineNum();
                    equal_column = parser.getColumn();
                    value.setLength(0);
                    continue;
                }
                
                // 判断标签是否结束 ,当前标签为‘>’视为结束
                int endTagIndex = ch == _GATHER_ ? value.length() - 1 : -1;
                if (endTagIndex > 0 && value.charAt(endTagIndex - 1) == _SLASH_)
                    endTagIndex--;// 如果是 ‘/>’ 结束则需要重置 结束索引 为‘/’对应的索引
                    
                if (endTagIndex != -1)
                {
                    variableName = StrUtils.trim(value.substring(0, endTagIndex));
                    String error = null;
                    if (variableName.length() == 0)
                        error = StrUtils.formats("%s标签解析结束，未找到变量定义", getType());
                    if (!Validates.isJavaNameIdentifier(variableName))
                        error = StrUtils.formats("%s标签解析时无效变量名,请参见java命名规范。数据值【%s】", getType(), variableName);
                    
                    if (error == null)
                        error = StrUtils.formats("%s标签解析结束，变量【%s】尚未初始化", getType(), variableName);
                    throw new StatementException(this.getPath(), expression_begin_line, expression_begin_column, error);
                }
                
                continue;
            }
            
            // 解析数据值
            if (quote == 0 && (ch == _DOUBLE_QUOTE_ || ch == _QUOTE_))
            {// 记录 字符串开始
                quote = ch;
                continue;
            }
            
            // 字符串结束
            if (quote != 0 && prvChar != _BACK_SLASH_ && ch == quote)
            {
                quote = 0;
                continue;
            }
            
            // 判断标签是否结束 ,当前标签为‘>’视为结束
            int endTagIndex = ch == _GATHER_ ? value.length() - 1 : -1;
            if (endTagIndex > 0 && value.charAt(endTagIndex - 1) == _SLASH_)
                endTagIndex--;// 如果是 ‘/>’ 结束则需要重置 结束索引 为‘/’对应的索引
            else
                endTagIndex = -1;
            
            if (quote == 0 && endTagIndex != -1)
            {//
                if (endTagIndex == 0)
                    throw new StatementException(this.getPath(), equal_line, equal_column, StrUtils.format("%s标签变量[%s]未初始化或者未赋予表达式", getType(), variableName));
                
                this.setStatement(this.getStatement() + " " + variableName + '=' + value);
                this.setCompleteTag();
                value.setLength(endTagIndex);
                this.parseExpression(expression_begin_line, expression_begin_column, value);// 解析表达式
                break;
            }
        }
        
        if (variableName == null)
            return false;// 文档已结束
            
        if (!this.isCompleteTag())
            throw new StatementException(this.getPath(), this.getLineNo(), this.getBeginColumn(), "文档已结束。" + getType() + "标签未找到结束符‘/>’");
        
        // 最后返回解析成功
        this.setStatement(this.getStatement() + " "+ this.variableName+" = "+expressions.get(0) + getType().getTagComplete());
        return true;
    }
}
